/**
 * @author : xwj
 * @date : 2021/9/21 23:53
 * @description : 给你一个链表，每 k 个节点一组进行翻转，请你返回翻转后的链表。
 *                k 是一个正整数，它的值小于或等于链表的长度。
 *                如果节点总数不是 k 的整数倍，那么请将最后剩余的节点保持原有顺序。
 *                进阶：
 *                  你可以设计一个只使用常数额外空间的算法来解决此问题吗？
 *                  你不能只是单纯的改变节点内部的值，而是需要实际进行节点交换。
 * @class : test25
 **/

public class test25 {

    public static class ListNode {
        int val;
        ListNode next;
        ListNode() {}
        ListNode(int val) { this.val = val; }
        ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    }

    //1. 0 ms	38.5 MB
    /*
    * 将链表进行分组，每k个一组，保留每一组节点的前一个节点，用于将每组节点进行倒序，采用递归的方式将每组进行倒序
    * 当一组节点的个数小于k值时，就直接退出。
    * */
    public static ListNode reverseKGroup(ListNode head, int k) {
        ListNode pre = new ListNode(0, head);
        ListNode p = pre;
        while (lengthOfGroup(head) >= k) {
            swapPairs(p, head, 1, k);
            p = head;
            head = head.next;
        }
        return pre.next;
    }

    public static void swapPairs(ListNode p, ListNode head, int count, int k) {
        if (count >= k) {
            return;
        }
        ListNode t = head.next.next;
        ListNode pre = p.next;
        p.next = head.next;
        head.next = t;
        p.next.next = pre;
        swapPairs(p, head, ++count, k);
    }

    public static int lengthOfGroup(ListNode head) {
        int count = 0;
        ListNode p = head;
        while (p != null) {
            count++;
            p = p.next;
        }
        return count;
    }

    public static void main(String[] args) {
        ListNode n4 = new ListNode(5);
        ListNode n3 = new ListNode(4, n4);
        ListNode n2 = new ListNode(3, n3);
        ListNode n1 = new ListNode(2, n2);
        ListNode head = new ListNode(1, n1);

        ListNode n = reverseKGroup(head, 2);

        show(n);
    }

    public static void show(ListNode n) {
        while (n != null) {
            System.out.println(n.val);
            n = n.next;
        }
    }

}
